﻿using System;
using System.Net;
using System.Windows;
using System.Diagnostics;
using System.ServiceModel;
using System.ComponentModel;

namespace NASA.BeAMartian.Extender
{
    public static class ClientBaseExtender
    {
        /// <summary>
        /// Tries to execute async service call. If <see cref="TimeoutException"/> occured retries again.
        /// USAGE:
        /// 
        /// var client = new MyServiceClient();
        /// client.ExecuteAsyncRepeatedly(() => client.MyOperationAsync(SecurityController.Instance.Login),
        ///        (EventHandler<MyOperationCompletedEventArgs> handler) => client.MyOperationCompleted += handler,
        ///        (s, e) => // OnCompleted
        ///                {
        ///                        Do(e.Result);
        ///                },
        ///        (s, e) => // OnError
        ///                {
        ///                        HandleError(e.Error);
        ///                }
        ///);

        /// </summary>
        /// <typeparam name="TChannel">ServiceClient class.</typeparam>
        /// <typeparam name="TArgs">Type of service client method return argument.</typeparam>
        /// <param name="client">ServiceClient instance.</param>
        /// <param name="tryExecute">Delegate that execute starting of service call.</param>
        /// <param name="onCompletedSubcribe">Delegate that subcribes an event handler to the OnCompleted event of the service client method.</param>
        /// <param name="onCompletedUnsubcribe">Delegate that unsubcribes an event handler to the OnCompleted event of the service client method.</param>
        /// <param name="onCompleted">Delegate that executes when service call is succeeded.</param>
        /// <param name="onError">Delegate that executes when service call fails.</param>
        /// <param name="maxAttempts">Maximum attempts to execute service call before error if <see cref="TimeoutException"/> occured (by default 5).</param>
        /// 
        public static ClientBaseExecutionClass<TChannel, TArgs> ExecuteAsyncRepeatedly<TChannel, TArgs>(
               this ClientBase<TChannel> client, 
               Action tryExecute,
               Action<EventHandler<TArgs>> onCompletedSubcribe,
               Action<EventHandler<TArgs>> onCompletedUnsubcribe, 
               EventHandler<TArgs> onCompleted, 
               int maxAttempts)
            where TChannel : class
            where TArgs : AsyncCompletedEventArgs
        {
            return new ClientBaseExecutionClass<TChannel, TArgs>(
                client,
                tryExecute,
                onCompletedSubcribe,
                onCompletedUnsubcribe,
                onCompleted,
                maxAttempts).Run();
        }
    }
}